package com.adwyxx.reflection;

import java.io.*;

/**
 * 类的加载与ClassLoader的理解：
 *
 * <p>类在内存中完整的生命周期：加载-->使用-->卸载。其中`加载`过程又分为：装载、链接、初始化三个阶段：</p>
 * <pre>
 *                 +-----------------------[链接 Linking]--------------------+
 * [加载 Loading]-->[验证 Verification]-->[准备 Preparation]-->[解析 Resolution]-->[初始化 Initialization]-->[使用 Using]-->[卸载 Unloading]
 *                 +-----------------------[链接 Linking]--------------------+
 *
 * （1）装载（Loading）
 *   将类的 class 文件读入内存，并为之创建一个 java.lang.Class 对象，此过程由类加载器完成。
 * （2）链接（Linking）
 *   ① 验证 Verify：确保加载的类信息符合JVM规范，例如：以cafebabe开头，没有安全方面的问题。
 *   ② 准备 Prepare：正式为类变量（static）分配内存并设置类变量默认初始值的阶段，这些内存都将在方法区中进行分配。
 *   ③ 解析 Resolve：虚拟机常量池内的符号引用（常量名）替换为直接引用（地址）的过程。
 * （3）初始化（Initialization）
 *   ① 执行类构造器<clinit>()方法的过程。类构造器<clinit>()方法是由编译期自动收集类中所有类变量的赋值动作和静态代码块中的语句合并产生的。（类构造器是构造类信息的，不是构造该类对象的构造器）。
 *   ② 当初始化一个类的时候，如果发现其父类还没有进行初始化，则需要先触发其父类的初始化。
 *   ③ 虚拟机会保证一个类的<clinit>()方法在多线程环境中被正确加锁和同步。
 * </pre>
 * <p>
 * 类加载器（ClassLoader）的作用是：将指定的类名加载到JVM中:
 * 将class文件字节码内容加载到内存中，并将这些静态数据转换成方法区的运行时数据结构，然后在堆中生成一个代表这个类的java.lang.Class对象，作为方法区中类数据的访问入口。
 * </p>
 * <pre>
 *                +--------------------------- JVM -----------------------------+
 *       +---loadClass()---+                     +---------getClass()-------+   |
 *       |        |        |                     ↓                          |   |
 *       ↓        |  ClassLoader --> Class<User> 对象 --newInstance()-> User 实例 |
 *  User.class -->|     ↑                    |                                  |
 *                |     +--getClassLoader()--+                                  |
 *                +--------------------------- JVM -----------------------------+
 * </pre>
 * <p>类加载器种类：</p>
 * <pre>
 * 1. BootstrapClassLoader：启动类加载器，负责加载JDK中的核心类库，如：rt.jar、resources.jar、charsets.jar等。
 * 2. ExtensionClassLoader：扩展类加载器，负责加载JDK中扩展目录中的jar包，如：jre/lib/ext/目录下的jar包。
 * 3. AppClassLoader：应用程序类加载器，负责加载用户类路径（ClassPath）所指定的jar包及目录。
 * 4. 自定义类:通常需要继承于ClassLoader类，并重写findClass()方法。如：Tomcat，Spring等中间件和组件框架都在内部实现了自定义的加载器，并通过自定义加载器隔离不同的组件模块。
 * </pre>
 *
 * @author Leo.W
 * @date 2024-09-06 9:28
 * @see ClassLoader
 */
public class ClassLoaderDemo {

    public static void main(String[] args) {
        // 1. 获取系统类加载器
        ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
        System.out.println(systemClassLoader); // jdk.internal.loader.ClassLoaders$AppClassLoader@1f89ab83

        // 2. 获取系统类加载器的父类加载器：扩展类加载器
        ClassLoader extClassLoader = systemClassLoader.getParent();
        System.out.println(extClassLoader); // jdk.internal.loader.ClassLoaders$PlatformClassLoader@1b6d3586

        // 3. 获取扩展类加载器的父类加载器：引导类加载器
        ClassLoader bootstrapClassLoader = extClassLoader.getParent();
        System.out.println(bootstrapClassLoader); // null

        // 4. 测试当前类是由哪个类加载器加载的
        ClassLoader classLoader = ClassLoaderDemo.class.getClassLoader();
        System.out.println(classLoader); // jdk.internal.loader.ClassLoaders$AppClassLoader@1f89ab83

        // 如果是根加载器加载的类，则会得到null
        System.out.println(Object.class.getClassLoader()); // null

        // getResourceAsStream(String str):获取类路径下的指定文件的输入流
        // 此时默认的相对路径是当前module的src目录
        InputStream inputStream = classLoader.getResourceAsStream("com/adwyxx/reflection/ClassLoaderDemo.class");
        if (inputStream != null) {
            try {
                //StringBuffer stringBuffer = new StringBuffer();
                InputStreamReader reader = null;
                reader = new InputStreamReader(inputStream, "UTF-8");
                BufferedReader br = new BufferedReader(reader);
                //BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream,"utf8"));
                String line;
                while ((line = br.readLine()) != null) {
                    //stringBuffer.append(line);
                    System.out.println(line);
                }
                br.close();
                reader.close();

            } catch (IOException e) {
                throw new RuntimeException(e);
            }

        }

    }
}
